//@ts-nocheck
import type { Plugin } from 'vite';
import { normalizePath } from 'vite';

const cache = new Map<string, boolean>();

const isDepInclude = (
  id: string,
  depPaths: string[],
  importChain: string[],
): boolean | undefined => {
  // compat windows
  id = normalizePath(id);
  const key = `${id}-${depPaths.join('|')}`;

  // circular dependency
  if (importChain.includes(id)) {
    cache.set(key, false);
    return false;
  }
  if (cache.has(key)) {
    return cache.get(key);
  }
  if (depPaths.includes(id)) {
    importChain.forEach((item) =>
      cache.set(`${item}-${depPaths.join('|')}`, true),
    );
    return true;
  }
  const moduleInfo = getModuleInfo(id);
  if (!moduleInfo || !moduleInfo.importers) {
    cache.set(key, false);
    return false;
  }
  const isInclude = moduleInfo.importers.some((importer: any) =>
    isDepInclude(importer, depPaths, importChain.concat(id), getModuleInfo),
  );
  // set cache, important!
  cache.set(key, isInclude);
  return isInclude;
};

export default (options: any): Plugin => {
  return {
    name: 'vite-plugin-split',
    apply: 'build',
    async config() {
      return {
        build: {
          rollupOptions: {
            output: {
              manualChunks: (id: string, { getModuleInfo }: any) => {
                for (const option of Object.keys(options)) {
                  const deps = options[option];
                  if (
                    id.includes('node_modules') &&
                    // 递归向上查找引用者，检查是否命中 options 声明的包
                    isDepInclude(id, deps, [], getModuleInfo)
                  ) {
                    return option;
                  }
                }
              },
            },
          },
        },
      };
    },
  };
};
